package handler

import (
	"context"
	"errors"

	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/emptypb"
	"gorm.io/gorm"

	"mxshop_srvs/userop_srv/model"
	proto "mxshop_srvs/userop_srv/proto/gen/v1"
)

func AddressModelToPb(a model.Address) *proto.AddressEntity {
	return &proto.AddressEntity{
		Id: int32(a.ID),
		Address: &proto.Address{
			UserId:       a.UserID,
			Province:     a.Province,
			City:         a.City,
			District:     a.District,
			Address:      a.Address,
			SignerName:   a.SignerName,
			SignerMobile: a.SignerMobile,
		},
	}
}

func (s *Service) GetAddressList(_ context.Context, req *proto.GetAddressListRequest) (*proto.AddressListResponse, error) {
	addresses, err := s.DB.GetAddresses(req.UserId)
	if err != nil {
		return nil, status.Error(codes.Internal, "")
	}

	data := make([]*proto.AddressEntity, 0, len(addresses))
	for _, a := range addresses {
		data = append(data, AddressModelToPb(a))
	}

	return &proto.AddressListResponse{
		Total:     int32(len(addresses)),
		Addresses: data,
	}, nil
}

func (s *Service) CreateAddress(_ context.Context, req *proto.Address) (*proto.AddressEntity, error) {
	ID, err := s.DB.CreateAddress(req)
	if err != nil {
		return nil, status.Error(codes.Internal, "")
	}

	return &proto.AddressEntity{
		Id:      int32(ID),
		Address: req,
	}, nil
}

func (s *Service) DeleteAddress(_ context.Context, req *proto.DeleteAddressRequest) (*emptypb.Empty, error) {
	row, err := s.DB.DeleteAddress(req.Id, req.UserId)
	if err != nil {
		return nil, status.Error(codes.Internal, "")
	}
	if row == 0 {
		return nil, status.Error(codes.NotFound, "收货地址不存在")
	}
	return &emptypb.Empty{}, nil
}

func (s *Service) UpdateAddress(_ context.Context, req *proto.AddressEntity) (*emptypb.Empty, error) {
	row, err := s.DB.UpdateAddress(req)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, status.Error(codes.NotFound, "收货地址不存在")
		}
		return nil, status.Error(codes.Internal, "")
	}

	if row == 0 {
		return nil, status.Error(codes.InvalidArgument, "更新失败")
	}
	return &emptypb.Empty{}, nil
}
